Skip to content

feat(browseros): --gn-arg overrides for configure#1516

Merged
Nikhil (shadowfax92) merged 1 commit into
mainfrom
feat/gn-arg-passthrough
Jul 2, 2026
Merged

feat(browseros): --gn-arg overrides for configure#1516
Nikhil (shadowfax92) merged 1 commit into
mainfrom
feat/gn-arg-passthrough

Conversation

@shadowfax92

Copy link
Copy Markdown
Contributor

Summary

  • Adds a repeatable browseros build --gn-arg key=value passthrough, accepted in all three build modes (preset/profile, modules-profiles, and direct --modules/phase flags).
  • ConfigureModule appends the values last in args.gn under a # --gn-arg overrides comment — GN last-write-wins makes them authoritative over the committed flags files, so iterating on chromium_patches no longer means editing config/gn/*.gn to flip symbol_level, dcheck_always_on, etc.
  • Per-invocation by design: no profile key, never persisted. Overrides surface in --show-plan headers, the run banner, and a configure-time Applying N gn-arg override(s) log line; a plan without configure warns that the flag has no effect.

Design

The CLI validates each value once (^[a-zA-Z_][a-zA-Z0-9_]*=.+ — clear error naming the offending value) and threads a verbatim tuple[str, ...] through Context.extra_gn_args; both resolver paths (resolve_config for direct/modules-profile mode, the preset projection's build_runs) set it, and configure is the only consumer. Values pass through verbatim per GN syntax: bools/ints bare, strings with embedded quotes (--gn-arg 'target_cpu="arm64"').

Test plan

  • uv run python -m unittest discover -s bos_build -t . -p "*_test.py" — 489 tests green (new: append-last + override-ordering + log in configure_test; threading/default in resolver_test; validation, --help repeatability, 3× show-plan headers, preset + modules-profile build_runs plumbing in build_test)
  • uv run ruff check bos_build
  • uv run browseros build --help | grep gn-arg · --list · product doctor
  • Smoke: --preset debug --gn-arg symbol_level=2 --gn-arg 'target_cpu="arm64"' --show-plan shows the overrides header; --gn-arg bogus rejected with a clear error

Repeatable 'browseros build --gn-arg key=value' passthrough, accepted in
preset/profile, modules-profile, and direct (--modules/phase-flag) modes.
ConfigureModule appends the values last in args.gn under a
'# --gn-arg overrides' comment, so GN last-write-wins makes them
authoritative over the committed flags files — no more editing
config/gn/*.gn to flip symbol_level or dcheck_always_on while iterating
on chromium_patches.

Values are validated (key=value shape) but pass through verbatim; they
are per-invocation by design (no profile key). Overrides surface in
--show-plan headers, the run banner, and a configure-time log line so a
build log always reveals a non-standard configuration.
@shadowfax92

Copy link
Copy Markdown
Contributor Author

Greptile (@greptileai) review

@shadowfax92

Copy link
Copy Markdown
Contributor Author

Claude (@claude) review

@claude

claude Bot commented Jul 2, 2026

Copy link
Copy Markdown

Claude finished Nikhil (@shadowfax92)'s task in 2m 43s —— View job


Code Review — feat(browseros): --gn-arg overrides for configure

  • Gather context and read changed files
  • Review cli/build.py — argument definition and wiring
  • Review core/context.py + core/resolver.py — data threading
  • Review steps/setup/configure.py — GN override injection
  • Review tests (build_test.py, resolver_test.py, configure_test.py)
  • Review README.md docs update
  • Post final review summary

Overall

Well-designed feature. All three build modes (preset, modules-profile, direct) thread extra_gn_args correctly, the GN last-write-wins semantics are properly implemented, and test coverage is comprehensive. No bugs found.


cli/build.py

Validation — _parse_gn_args (line 704–716)

The regex ^[a-zA-Z_][a-zA-Z0-9_]*=.+\Z is solid:

  • \Z (not $) prevents trailing-newline bypass — a shell expansion like $(printf 'symbol_level=2\n') would be caught where $ would silently pass it through.
  • .+ correctly rejects empty values (symbol_level=).
  • The GN identifier character set [a-zA-Z0-9_] matches GN's own spec.

One edge case worth noting: the regex permits values with embedded spaces, e.g. --gn-arg 'foo=bar baz'. This is a GN syntax error at build time but passes CLI validation. The PR description documents that values are passed verbatim, so this is intentional — just not obvious from the help text. Worth a doc note if users hit confusing gn gen failures.

Warning check (line 379)

if not any("configure" in run_steps for _, run_steps in runs):

"configure" in run_steps tests list membership (element equality), not substring match — this is correct. Only fires when the exact step "configure" is absent from all run pipelines, which is exactly when the override has no effect. Good UX.

_resolve_modules_profile--sign/--upload gate (line 638)

rejected = {
    ...
    "--sign/--no-sign": sign,
    "--upload/--no-upload": upload,
    ...
}
given = sorted(flag for flag, value in rejected.items() if value is not None)

sign and upload are Optional[bool] so if value is not None correctly catches both True and False. Pre-existing behavior confirmed correct.


core/context.py (line 83)

extra_gn_args: tuple[str, ...] = ()

Minor style note: this file imports Dict, Optional from typing (PEP 484 style) but uses PEP 585 builtins here (tuple[str, ...]). Not a bug — the same file already uses lowercase list[str] and list[Path] in method return types (get_product_gn_args, get_chromium_replace_roots), so the PR follows the file's existing mixed style.


steps/setup/configure.py (lines 65–71)

if ctx.extra_gn_args:
    log_info(
        f"🔧 Applying {len(ctx.extra_gn_args)} gn-arg override(s): "
        f"{', '.join(ctx.extra_gn_args)}"
    )
    args_content += "\n# --gn-arg overrides\n"
    args_content += "\n".join(ctx.extra_gn_args) + "\n"

Clean. The \n# --gn-arg overrides\n separator makes overrides visually distinct in args.gn for debugging. The trailing \n after "\n".join(...) ensures a properly-terminated file.

One thought: the GN args are written as key=value (no spaces around =), but GN's canonical style is key = value. This is fine — GN accepts both forms — but a user inspecting args.gn will see the flags file use key = value style while overrides use key=value. Not a correctness issue; just a cosmetic asymmetry. Fix this →


steps/setup/configure_test.py (line 74)

ctx.extra_gn_args = extra_gn_args

This directly mutates the dataclass after construction rather than passing through make_context. Works fine since Context isn't frozen. A minor alternative would be dataclasses.replace(ctx, extra_gn_args=extra_gn_args), but the direct mutation is perfectly readable in test context.

The test_extra_gn_arg_overriding_flags_key_lands_after_it test (line 132) is a good regression guard — it proves the override positionally trails the flags file entry (index comparison), verifying GN's last-write-wins behavior independently of GN itself.


Tests summary

  • Validation: test_malformed_gn_arg_rejected, test_empty_gn_arg_value_rejected
  • Threading: test_extra_gn_args_threaded_to_context, test_extra_gn_args_default_empty
  • Preset plumbing: test_preset_build_runs_carry_extra_gn_args
  • Modules-profile plumbing: test_modules_profile_build_runs_carry_extra_gn_args
  • Show-plan headers (all 3 modes): ✓
  • Configure behavior: append-last, ordering, logging ✓
  • Help text repeatability: test_help_documents_repeatable

No missing coverage gaps.


Summary

Approve. The implementation is correct, all three build paths are properly wired, the validation is sound, and tests cover the important cases. The two cosmetic notes (type hint style, key=value vs key = value in args.gn) are non-blocking.

@shadowfax92 Nikhil (shadowfax92) merged commit 78b40e4 into main Jul 2, 2026
5 of 6 checks passed
@greptile-apps

greptile-apps Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds a repeatable --gn-arg key=value CLI flag to browseros build that appends GN variable overrides at the end of args.gn after all committed flags files, leveraging GN's last-write-wins semantics to make them authoritative without editing committed config files.

  • _parse_gn_args validates each value against ^[a-zA-Z_][a-zA-Z0-9_]*=.+\\Z at CLI entry, and a validated tuple[str, ...] is threaded through Context.extra_gn_args into all three build modes (preset, modules-profile, direct).
  • ConfigureModule.execute appends the overrides verbatim last in args.gn under a comment block and logs the count; a run-time warning fires when configure is absent from the plan, preventing silent no-ops.
  • Test coverage is comprehensive (489 tests), covering validation rejection, plan-header display across all three modes, plumbing to Context in both resolver paths, append ordering, and log verification.

Confidence Score: 4/5

Safe to merge; the feature is well-scoped, thoroughly tested, and the core append-last write to args.gn is straightforward and correct.

The implementation is clean and test coverage is thorough across all three build modes. The no-effect warning (configure absent from plan) fires only at execution time and is silent during --show-plan, so a user previewing a sliced plan that skips configure will see the GN overrides in the header without any hint they will be ignored. The regex also allows whitespace-only values through validation, which GN would reject with a generic error. Neither is a blocking defect, but both are worth fixing for a better developer experience.

cli/build.py — the no-effect warning placement and the regex value constraint.

Important Files Changed

Filename Overview
packages/browseros/bos_build/cli/build.py Adds --gn-arg CLI option with validation, threads extra_gn_args through all three build modes (preset, modules-profile, direct), and adds plan-header and banner surfacing. Minor: no-effect warning is only visible at execution time, not during --show-plan.
packages/browseros/bos_build/core/context.py Adds extra_gn_args: tuple[str, ...] = () field to Context dataclass with a clear doc comment. Clean addition; not used in post_init, so post-construction assignment in tests is safe.
packages/browseros/bos_build/core/resolver.py Picks up extra_gn_args from cli_args dict and passes it to Context constructor for direct mode. Correct use of tuple(... or ()) guard for None safety.
packages/browseros/bos_build/steps/setup/configure.py Appends extra_gn_args verbatim last in args.gn under a comment block, logs count before writing. GN last-write-wins semantics make this authoritative over earlier flags.
packages/browseros/bos_build/cli/build_test.py Comprehensive test coverage: malformed/empty arg rejection, help text, --show-plan headers for all three modes, and build_runs() plumbing for preset and modules-profile paths.
packages/browseros/bos_build/steps/setup/configure_test.py Adds tests for append-last ordering, override-wins-over-flags ordering, and log_info call verification. Direct assignment ctx.extra_gn_args = extra_gn_args is safe on an unfrozen dataclass.
packages/browseros/bos_build/core/resolver_test.py Adds tests for extra_gn_args threading to Context and default empty tuple. Clean coverage of both threaded and default cases.
packages/browseros/bos_build/README.md Accurately documents --gn-arg semantics, verbatim GN syntax requirements, CLI-only intent, and caveats around reuse when configure is skipped.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant CLI as CLI (build.py)
    participant Parser as _parse_gn_args
    participant Resolver as resolve_config / _resolve_preset
    participant Ctx as Context
    participant Configure as ConfigureModule.execute
    participant ArgsGn as args.gn

    CLI->>Parser: gn_arg list from --gn-arg flags
    Parser-->>CLI: validated tuple[str,...]
    alt preset / modules-profile mode
        CLI->>Resolver: "_resolve_preset(extra_gn_args=...)"
        Resolver->>Ctx: "Context(extra_gn_args=extra_gn_args)"
    else direct mode
        CLI->>Resolver: "resolve_config({extra_gn_args: ...})"
        Resolver->>Ctx: "Context(extra_gn_args=extra_gn_args)"
    end
    Ctx-->>CLI: runs [(ctx, steps)]
    CLI->>Configure: execute(ctx)
    Configure->>ArgsGn: write flags_file + target_cpu + product_args
    Configure->>ArgsGn: "append # --gn-arg overrides + extra_gn_args"
    Configure->>Configure: gn gen out/dir
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant CLI as CLI (build.py)
    participant Parser as _parse_gn_args
    participant Resolver as resolve_config / _resolve_preset
    participant Ctx as Context
    participant Configure as ConfigureModule.execute
    participant ArgsGn as args.gn

    CLI->>Parser: gn_arg list from --gn-arg flags
    Parser-->>CLI: validated tuple[str,...]
    alt preset / modules-profile mode
        CLI->>Resolver: "_resolve_preset(extra_gn_args=...)"
        Resolver->>Ctx: "Context(extra_gn_args=extra_gn_args)"
    else direct mode
        CLI->>Resolver: "resolve_config({extra_gn_args: ...})"
        Resolver->>Ctx: "Context(extra_gn_args=extra_gn_args)"
    end
    Ctx-->>CLI: runs [(ctx, steps)]
    CLI->>Configure: execute(ctx)
    Configure->>ArgsGn: write flags_file + target_cpu + product_args
    Configure->>ArgsGn: "append # --gn-arg overrides + extra_gn_args"
    Configure->>Configure: gn gen out/dir
Loading
Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 2
packages/browseros/bos_build/cli/build.py:377-383
**No-effect warning silent during `--show-plan`**

The `--gn-arg has no effect` warning only fires during actual execution (after `build_runs()` is called on line 328), but `--show-plan` returns on line 277 before ever reaching the banner block. A user running `--preset release --from compile --gn-arg symbol_level=2 --show-plan` will see `GN arg overrides: symbol_level=2` in the plan header, with no indication that configure is absent from the sliced plan and the override is a no-op. The header lists the GN args truthfully, but a co-located note in `--show-plan` output would prevent confusion.

### Issue 2 of 2
packages/browseros/bos_build/cli/build.py:704
**Regex permits whitespace-only values**

`_GN_ARG_RE` uses `.+` for the value, which allows `key=   ` (whitespace-only string) to pass validation. GN would reject or silently misbehave on such args depending on the expected type (e.g. boolean or integer args don't accept whitespace). Changing `.+` to `\S.*` (value must start with a non-whitespace character) would reject these before they cause a confusing `gn gen` error downstream.

```suggestion
_GN_ARG_RE = re.compile(r"^[a-zA-Z_][a-zA-Z0-9_]*=\S.*\Z")
```

Reviews (1): Last reviewed commit: "feat(browseros): --gn-arg overrides for ..." | Re-trigger Greptile

Comment on lines +377 to +383
if summary_ctx.extra_gn_args:
log_info(f"📍 GN arg overrides: {', '.join(summary_ctx.extra_gn_args)}")
if not any("configure" in run_steps for _, run_steps in runs):
log_warning(
"⚠️ --gn-arg has no effect: no run in this plan includes the "
"configure step, so args.gn is reused as-is"
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 No-effect warning silent during --show-plan

The --gn-arg has no effect warning only fires during actual execution (after build_runs() is called on line 328), but --show-plan returns on line 277 before ever reaching the banner block. A user running --preset release --from compile --gn-arg symbol_level=2 --show-plan will see GN arg overrides: symbol_level=2 in the plan header, with no indication that configure is absent from the sliced plan and the override is a no-op. The header lists the GN args truthfully, but a co-located note in --show-plan output would prevent confusion.

Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/browseros/bos_build/cli/build.py
Line: 377-383

Comment:
**No-effect warning silent during `--show-plan`**

The `--gn-arg has no effect` warning only fires during actual execution (after `build_runs()` is called on line 328), but `--show-plan` returns on line 277 before ever reaching the banner block. A user running `--preset release --from compile --gn-arg symbol_level=2 --show-plan` will see `GN arg overrides: symbol_level=2` in the plan header, with no indication that configure is absent from the sliced plan and the override is a no-op. The header lists the GN args truthfully, but a co-located note in `--show-plan` output would prevent confusion.

How can I resolve this? If you propose a fix, please make it concise.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

return tuple(s.strip() for s in value.split(",") if s.strip())


_GN_ARG_RE = re.compile(r"^[a-zA-Z_][a-zA-Z0-9_]*=.+\Z")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Regex permits whitespace-only values

_GN_ARG_RE uses .+ for the value, which allows key= (whitespace-only string) to pass validation. GN would reject or silently misbehave on such args depending on the expected type (e.g. boolean or integer args don't accept whitespace). Changing .+ to \S.* (value must start with a non-whitespace character) would reject these before they cause a confusing gn gen error downstream.

Suggested change
_GN_ARG_RE = re.compile(r"^[a-zA-Z_][a-zA-Z0-9_]*=.+\Z")
_GN_ARG_RE = re.compile(r"^[a-zA-Z_][a-zA-Z0-9_]*=\S.*\Z")
Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/browseros/bos_build/cli/build.py
Line: 704

Comment:
**Regex permits whitespace-only values**

`_GN_ARG_RE` uses `.+` for the value, which allows `key=   ` (whitespace-only string) to pass validation. GN would reject or silently misbehave on such args depending on the expected type (e.g. boolean or integer args don't accept whitespace). Changing `.+` to `\S.*` (value must start with a non-whitespace character) would reject these before they cause a confusing `gn gen` error downstream.

```suggestion
_GN_ARG_RE = re.compile(r"^[a-zA-Z_][a-zA-Z0-9_]*=\S.*\Z")
```

How can I resolve this? If you propose a fix, please make it concise.

@greptile-apps

greptile-apps Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds a repeatable --gn-arg key=value CLI passthrough for the browseros build command, allowing developers to apply one-off GN flag overrides at configure time without editing committed flags files. The feature is per-invocation by design — validated at the CLI boundary, threaded as an immutable tuple[str, ...] through Context.extra_gn_args, and appended last in args.gn so GN's last-write-wins semantics make them authoritative over the flags file and product args.

  • All three build modes (preset, modules-profile, and direct --modules/phase flags) correctly receive extra_gn_args via resolve_config, and --show-plan headers display the overrides in every mode.
  • ConfigureModule.execute() appends the args after a # --gn-arg overrides comment; a runtime warning fires if configure is absent from the resolved pipeline (e.g. after --from compile).
  • Validation uses ^[a-zA-Z_][a-zA-Z0-9_]*=.+\Z to reject malformed values early with a clear error, and test coverage includes all three modes, bad-input rejection, show-plan headers, Context threading, and log output.

Confidence Score: 4/5

The change is well-scoped to the CLI and configure step; existing pipeline behaviour is untouched and the feature is per-invocation only.

All three build modes correctly thread extra_gn_args to Context and on to args.gn; validation, show-plan headers, the runtime warning, and test coverage are thorough. Two minor code-quality observations exist — direct attribute mutation in the test helper rather than the constructor, and the regex admitting a bare carriage return in values — but neither affects correctness in practice.

configure_test.py warrants a quick look at the make_context helper to confirm it supports extra_gn_args as a constructor parameter; everything else is straightforward.

Important Files Changed

Filename Overview
packages/browseros/bos_build/cli/build.py Adds --gn-arg CLI option with regex validation, threads extra_gn_args through all three build modes (preset, modules-profile, direct), and emits a clear warning when configure is not in the resolved pipeline.
packages/browseros/bos_build/core/context.py Adds extra_gn_args: tuple[str, ...] = () field to Context dataclass with a clear docstring; no issues.
packages/browseros/bos_build/core/resolver.py Correctly extracts extra_gn_args from cli_args dict and passes it to Context constructor in resolve_config; no issues.
packages/browseros/bos_build/steps/setup/configure.py Appends extra_gn_args verbatim after all other flags in args.gn, correctly exploiting GN's last-write-wins semantics; logging is informative.
packages/browseros/bos_build/steps/setup/configure_test.py Good coverage of append-order, override semantics, and logging; uses direct attribute mutation (ctx.extra_gn_args = ...) rather than passing through the constructor, which is functional but slightly inconsistent with typical dataclass usage.
packages/browseros/bos_build/cli/build_test.py Thorough test coverage across all three modes for validation, show-plan header, and Context threading; no issues.
packages/browseros/bos_build/core/resolver_test.py Adds two clear tests for threading and default-empty behaviour of extra_gn_args in resolve_config; no issues.
packages/browseros/bos_build/README.md Adds accurate documentation for --gn-arg flag including value format, CLI-only semantics, and resume/from interaction.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    CLI["browseros build --gn-arg key=value"]
    PARSE["_parse_gn_args()\nRegex: ^[a-zA-Z_][a-zA-Z0-9_]*=.+\\Z"]
    INVALID["log_error + Exit(1)"]
    MODE{Build mode?}
    PRESET["_resolve_preset()\nextra_gn_args threaded\nto build_runs()"]
    MODULES["_resolve_modules_profile()\nextra_gn_args → resolve_config()"]
    DIRECT["Direct mode\nresolve_config(cli_args)"]
    CTX["Context.extra_gn_args\n= tuple[str, ...]"]
    WARN{configure\nin run_steps?}
    WARNING["log_warning: --gn-arg\nhas no effect"]
    CONFIGURE["ConfigureModule.execute()"]
    ARGSGN["args.gn written:\n1. flags file\n2. target_cpu\n3. product args\n4. # --gn-arg overrides\n5. extra_gn_args (last-write-wins)"]
    GN["gn gen out_dir"]

    CLI --> PARSE
    PARSE -->|invalid| INVALID
    PARSE -->|valid tuple| MODE
    MODE -->|preset/profile| PRESET
    MODE -->|modules profile| MODULES
    MODE -->|modules/phase flags| DIRECT
    PRESET --> CTX
    MODULES --> CTX
    DIRECT --> CTX
    CTX --> WARN
    WARN -->|No| WARNING
    WARN -->|Yes| CONFIGURE
    CONFIGURE --> ARGSGN
    ARGSGN --> GN
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    CLI["browseros build --gn-arg key=value"]
    PARSE["_parse_gn_args()\nRegex: ^[a-zA-Z_][a-zA-Z0-9_]*=.+\\Z"]
    INVALID["log_error + Exit(1)"]
    MODE{Build mode?}
    PRESET["_resolve_preset()\nextra_gn_args threaded\nto build_runs()"]
    MODULES["_resolve_modules_profile()\nextra_gn_args → resolve_config()"]
    DIRECT["Direct mode\nresolve_config(cli_args)"]
    CTX["Context.extra_gn_args\n= tuple[str, ...]"]
    WARN{configure\nin run_steps?}
    WARNING["log_warning: --gn-arg\nhas no effect"]
    CONFIGURE["ConfigureModule.execute()"]
    ARGSGN["args.gn written:\n1. flags file\n2. target_cpu\n3. product args\n4. # --gn-arg overrides\n5. extra_gn_args (last-write-wins)"]
    GN["gn gen out_dir"]

    CLI --> PARSE
    PARSE -->|invalid| INVALID
    PARSE -->|valid tuple| MODE
    MODE -->|preset/profile| PRESET
    MODE -->|modules profile| MODULES
    MODE -->|modules/phase flags| DIRECT
    PRESET --> CTX
    MODULES --> CTX
    DIRECT --> CTX
    CTX --> WARN
    WARN -->|No| WARNING
    WARN -->|Yes| CONFIGURE
    CONFIGURE --> ARGSGN
    ARGSGN --> GN
Loading
Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 2
packages/browseros/bos_build/steps/setup/configure_test.py:71-74
The test sets `ctx.extra_gn_args` via direct attribute mutation after construction rather than passing the field through the constructor. Since `Context` is a non-frozen dataclass, this works, but `extra_gn_args` is a regular init parameter with a default, so it can be passed directly — keeping the context construction consistent with how all other fields are handled and making the intent clearer.

```suggestion
        ctx = make_context(
            chromium, root, architecture=architecture, build_type=build_type,
            extra_gn_args=extra_gn_args,
        )
```

### Issue 2 of 2
packages/browseros/bos_build/cli/build.py:704
**Regex accepts `\r` in values**

The pattern `.+` (without `re.DOTALL`) correctly rejects embedded newlines `\n`, but it does match carriage return `\r`. A value like `symbol_level=2\r` passes validation and is written verbatim into `args.gn`, which could cause a GN parse error on Unix. Replacing `.+` with `[^\r\n]+` closes this gap with no change to normal usage.

Reviews (2): Last reviewed commit: "feat(browseros): --gn-arg overrides for ..." | Re-trigger Greptile

return tuple(s.strip() for s in value.split(",") if s.strip())


_GN_ARG_RE = re.compile(r"^[a-zA-Z_][a-zA-Z0-9_]*=.+\Z")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Regex accepts \r in values

The pattern .+ (without re.DOTALL) correctly rejects embedded newlines \n, but it does match carriage return \r. A value like symbol_level=2\r passes validation and is written verbatim into args.gn, which could cause a GN parse error on Unix. Replacing .+ with [^\r\n]+ closes this gap with no change to normal usage.

Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/browseros/bos_build/cli/build.py
Line: 704

Comment:
**Regex accepts `\r` in values**

The pattern `.+` (without `re.DOTALL`) correctly rejects embedded newlines `\n`, but it does match carriage return `\r`. A value like `symbol_level=2\r` passes validation and is written verbatim into `args.gn`, which could cause a GN parse error on Unix. Replacing `.+` with `[^\r\n]+` closes this gap with no change to normal usage.

How can I resolve this? If you propose a fix, please make it concise.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant